
// ---------------------------------------------------
// | File Name   : temphumi.c
// | Author   	 : chagn7z
// | Create Date : 2014-6-16
// ---------------------------------------------------

#include "stm32f10x.h"
#include "user_cfg.h"
#include "temphumi.h"
#include "delay.h"
#include "include.h"

/* store temp&humi info */
temphumi_struct temphumi_info;

void temphumi_init(void)
{
	GPIO_InitTypeDef GPIO_InitType;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	/* GPIO_B Pin 9 for SCL */
	GPIO_InitType.GPIO_Pin   = GPIO_Pin_9;
	GPIO_InitType.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitType.GPIO_Mode  = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOB, &GPIO_InitType);
	
	/* GPIO_B Pin 8 for SDA */
	GPIO_InitType.GPIO_Pin   = GPIO_Pin_8;
	GPIO_InitType.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitType.GPIO_Mode  = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOB, &GPIO_InitType);	
}

/* syn temperature & humidity info to global struct */
void th_da_syn(void)
{
	u32 val;
	
	th_wakeup();
	th_wt_cmd();
	delay_us(1000);
	val = th_rd_data();
	
	temphumi_info.temp = val & 0x0000ffff;
	temphumi_info.humi = (val >> 16) & 0x0000ffff;
}

/* get return info from sensor */
u32 th_rd_data(void)
{
	u8 i;
	u8 cmdword;
	u8 len;
	u32 val=0;
	
	th_iic_start();
	th_wt_byte(0xb8 | 0x01);
	
	if (!th_dt_ack())
		return 0;
	
	delay_us(35);
	
	cmdword = th_rd_byte();
	th_ack();
	len     = th_rd_byte();
	th_ack();
	
	for (i=0; i<4; i++)
	{
		val <<= 8;
		val |= th_rd_byte();
		th_ack();
	}
	
	th_rd_byte();
	th_ack();
	th_rd_byte();
	th_ack();
	
	th_iic_stop();
	
	return val;	
}

/* send operator command to sensor */
u8 th_wt_cmd(void)
{

	th_iic_start();
	
	th_wt_byte(0xb8);
	if (!th_dt_ack())
		return 1;
		
	th_wt_byte(0x03);
	if (!th_dt_ack())
		return 2;	
		
	th_wt_byte(0x00);
	if (!th_dt_ack())
		return 3;	
		
	th_wt_byte(0x04);
	if (!th_dt_ack())
		return 4;
		
	th_iic_stop();
	
	return 0;
}

/* wakeup sensor */
void th_wakeup(void)
{
	th_iic_start();
	th_wt_byte(0xb8);
	th_dt_ack();
	delay_us(2000);
	th_iic_stop();
}

/* write one byte to iic bus */
void th_wt_byte(u8 buf)
{
	u8 i;
	
	pinc_set(TH_IO, TH_PORT_OUT);
	
	for (i=0; i<8; i++)
	{
		TH_SCL = 0;
		delay_us(TH_DE);
		
		if (buf & 0x80)
			TH_SO = 1;
		else 
			TH_SO = 0;
			
		TH_SCL = 1;
		delay_us(TH_DE);
		buf <<= 1;
	}
	
	TH_SCL = 0;
}

/* read one byte from iic bus */
u8 th_rd_byte(void)
{
	u8 i;
	u8 rd_da=0;
	
	pinc_set(TH_IO, TH_PORT_IN);
	
	for (i=0; i<8; i++)
	{
		TH_SCL = 0;
		delay_us(TH_DE);
		TH_SCL = 1;
		delay_us(TH_DE);
		
		rd_da <<= 1;
		if (TH_SI)
			rd_da |= 0x01;
	}
	
	TH_SCL = 0;
	
	return rd_da;
}

/* send start signal to iic bus */
void th_iic_start(void)
{
	pinc_set(TH_IO, TH_PORT_OUT);
	
	TH_SO  = 1;
	TH_SCL = 1;
	delay_us(TH_DE);
	TH_SO = 0;
	delay_us(TH_DE);
	TH_SCL = 0;
}

/* send stop signal to iic bus */
void th_iic_stop(void)
{
	pinc_set(TH_IO, TH_PORT_OUT);
	
	TH_SO  = 0;
	delay_us(TH_DE);
	TH_SCL = 1;
	delay_us(TH_DE);
	TH_SO  = 1;
}

/* send ack to iic bus from MCU */
void th_ack(void)
{
	pinc_set(TH_IO, TH_PORT_OUT);
	
	TH_SO  = 0;
	TH_SCL = 0;
	delay_us(TH_DE);
	TH_SCL = 1;
	delay_us(TH_DE);
	TH_SCL = 0;
	TH_SO  = 1;
}

/* send noack to iic bus from MCU */
void th_noack(void)
{
	pinc_set(TH_IO, TH_PORT_OUT);
	
	TH_SO  = 1;
	TH_SCL = 0;
	delay_us(TH_DE);
	TH_SCL = 1;
	delay_us(TH_DE);
	TH_SCL = 0;
	TH_SO  = 1;
}

/* detect ack from sensor */
u8 th_dt_ack(void)
{
	u8 ack_flag = 0;
	
	pinc_set(TH_IO, TH_PORT_OUT);
	TH_SCL = 0;
//	TH_SO  = 1;
	pinc_set(TH_IO, TH_PORT_IN);
	delay_us(TH_DE+2);
	TH_SCL = 1;
	delay_us(TH_DE+2);
	
	if (TH_SI)
		ack_flag = 0;
	else
		ack_flag = 1;
		
	TH_SCL = 0;
	
	return ack_flag;
}

void pinc_set(u16 pin, u8 io)
{
	GPIO_InitTypeDef GPIO_InitType;
	
	GPIO_InitType.GPIO_Pin   = pin;
	GPIO_InitType.GPIO_Speed = GPIO_Speed_50MHz;
	
	if (io)
		GPIO_InitType.GPIO_Mode  = GPIO_Mode_Out_PP;
	else 
		GPIO_InitType.GPIO_Mode  = GPIO_Mode_IPU;
		
	GPIO_Init(GPIOC, &GPIO_InitType);
}


